package com.anonymous.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

/* Author : Sungkyu Kang
 * Description : 
 * This class implements database connection pooling. 
 * Clients are expected to make use of getConnection(), putBackConnection(Connection con) method to acquire and release.
 * It create connection on-demand basis. Clients must close Statement and ResultSet before call putBackConnection.
 * 
 */
public class ConnectionPool {

	private Vector<Connection> connections ;
	private int maxCon;
	private int totalCon;
	private String dbName = null;
	
	public ConnectionPool(int maxCon
							,String dbName
							,String driverName){

		initialize(maxCon, dbName, driverName);
	}
	
	public ConnectionPool(){
		initialize(10, "jdbc:sqlite:test.sqlite","org.sqlite.JDBC" );
	}
	
	private void initialize(int maxCon, String dbName, String driverName)  {

		try {
			Class.forName(driverName);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Database driver could not be loaded");
			System.out.println("Check the class library or driver name");
			System.exit(0);
		}
		this.maxCon = maxCon;
		this.dbName = dbName;

		this.totalCon = 0;
		this.connections = new Vector<Connection>(maxCon);	

	}

	private void initialize() throws ClassNotFoundException{
	}
	
	/*
	 * If the number of connections exceeded maxCon, and the pool is empty, 
	 * thread waits for next available one.
	 * If putBackConnection(Connection c) is invoked, it will either put back
	 * or decrease totalCon indicating the connection is no longer valid.
	 */
	public synchronized Connection getConnection(){
		Connection con = null;
		while(connections.size() == 0 && totalCon >= maxCon) {
			try{
				wait();
			} catch(InterruptedException e){
				
			}
		}
		if(connections.size()>0){
			con = connections.remove(0);
		}else{
			try{
				con = DriverManager.getConnection(dbName);
				//System.out.println("		 new connection created");
				con.setAutoCommit(true);
			}catch(Exception e){
			}
			if(con != null) totalCon++;
		}
		/*
		System.out.println("getConnection invoked");
		System.out.println("	Vector size  = " + connections.size());
		System.out.println("	Total Connections = " + totalCon);
		System.out.println("	");
		System.out.println("");
		System.out.println("");*/
		return con;
	}
	
	/*
	 * Client invokes this method in an attempt to return a connection.
	 * Make sure to close Statement and ResultSet objects before calling this method.
	 */
	public synchronized void putBackConnection(Connection c){
		try{
			if(c.isClosed()) totalCon--;
			else connections.addElement(c);
		}catch(SQLException e){
			e.printStackTrace();
		}
		/*
		System.out.println("getConnection invoked");
		System.out.println("	Vector size  = " + connections.size());
		System.out.println("	Total Connections = " + totalCon);
		System.out.println("	");
		System.out.println("");
		System.out.println("");
	*/
		notifyAll();
	}
}